#pragma once
#include"types.h"
//内联函数
static inline void cli()            
{
    __asm__ __volatile("cli");    //关闭中断
}

static inline void sti()            
{
    __asm__ __volatile("sti");    //打开中断
}

static inline uint8_t inb(uint16_t port)   
{
    uint8_t ret;
    // inb al, dx
    __asm__ __volatile("inb %[p] ,%[val]" :[val]"=a"(ret) :[p] "d"(port));              //从端口读取一个字节
    return ret;
}


static inline uint16_t inw(uint16_t port)   
{
    uint16_t ret;
    // in ax, dx
    __asm__ __volatile("in %[p] ,%[val]" :[val]"=a"(ret) :[p] "d"(port));              //从端口读取一个字节
    return ret;
}

static inline void outb(uint16_t port,uint8_t data)
{
    //outb al, dx
    __asm__ __volatile("outb %[val] ,%[p]" :: [p] "d"(port), [val]"a"(data));           //向端口写入一个字节
}

static inline void outw(uint16_t port, uint16_t data) 
{
	__asm__ __volatile__("out %[v], %[p]" : : [p]"d" (port), [v]"a" (data));
}

//设置GDTR
static inline void lgdt(uint32_t start,uint16_t size)
{
    struct
    {
        uint16_t limit;             //描述符表大小-1
        uint16_t startl;            //低16位
        uint16_t starth;            //高16位
    }gdt;

    gdt.limit=size-1;
    gdt.starth=  start >> 16;
    gdt.startl=  start & 0xFFFF;

    __asm__ __volatile("lgdt %[g]" ::[g]"m"(gdt));
}

//设置CR0,PE位
static inline void CR0_PE()
{

    uint32_t cr0;

    //读取CR0
    __asm__("mov %%cr0, %0" :"=r"(cr0));

    //修改CR0
    cr0 |= 1; 

    //写回
    __asm__("mov %0, %%cr0" :: "r"(cr0));    
}



static inline void write_cr3(uint32_t v) 
{
    __asm__ __volatile__("mov %[v], %%cr3"::[v]"r"(v));
}


static inline uint32_t read_cr2() 
{
    uint32_t cr2;
    __asm__ __volatile__("mov %%cr2, %[v]":[v]"=r"(cr2));
    return cr2;
}

static inline uint32_t read_cr3() 
{
    uint32_t cr3;
    __asm__ __volatile__("mov %%cr3, %[v]":[v]"=r"(cr3));
    return cr3;
}

static inline uint32_t read_cr4() 
{
    uint32_t cr4;
    __asm__ __volatile__("mov %%cr4, %[v]":[v]"=r"(cr4));
    return cr4;
}

static inline void write_cr4(uint32_t v) 
{
    __asm__ __volatile__("mov %[v], %%cr4"::[v]"r"(v));
}

static inline uint32_t read_cr0() 
{
	uint32_t cr0;
	__asm__ __volatile__("mov %%cr0, %[v]":[v]"=r"(cr0));
	return cr0;
}

static inline void write_cr0(uint32_t v) 
{
	__asm__ __volatile__("mov %[v], %%cr0"::[v]"r"(v));
}

//远跳转
static inline void far_jump(uint32_t selector , uint32_t offset)
{

    uint32_t addr[]={offset,selector};  //offset->偏移量,selector->段选择子
    __asm__("ljmpl *(%[a])"::[a]"r"(addr));    
}


//设置IDTR
static inline void lidt(uint32_t start,uint16_t size)
{
    struct
    {
        uint16_t limit;             //描述符表大小-1
        uint16_t startl;            //低16位
        uint16_t starth;            //高16位
    }idt;

    idt.limit=size-1;
    idt.starth=  start >> 16;
    idt.startl=  start & 0xFFFF;

    __asm__ __volatile("lidt %[g]" ::[g]"m"(idt));
}


static inline void hlt()   
{
    __asm__ __volatile("hlt"); 
}


//设置IDTR
static inline void write_tr(uint16_t tss_sel)
{
    __asm__ __volatile("ltr %%ax" ::"a"(tss_sel));
}


static inline uint32_t read_eflags()
{
    uint32_t eflags;
    __asm__ __volatile("pushf\n\t pop %%eax" :"=a"(eflags));
    return eflags;
}

    
static inline void write_eflags(uint32_t eflags)
{
    __asm__ __volatile("push %%eax\n\t popf"::"a"(eflags));
}